package charts.series.pies ;

import charts.series.Element;
import charts.Pie;
import flash.display.Sprite;
import flash.display.GradientType;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.events.Event;
import flash.events.MouseEvent;
import caurina.transitions.Tweener;
import caurina.transitions.Equations;

class PieSlice extends Element {
	
	static var TO_RADIANS: Float = Math.PI / 180;
	var color: Float;
	public var slice_angle: Float;
	var border_width: Float;
	public var angle: Float;
	public var is_over:Bool;
	public var nolabels:Bool;
	var animate:Bool;
	var finished_animating:Bool;
	public var value: Int; // Float;
	var gradientFill:Bool;
	var label:String;
	var pieRadius: Int; //Float;
	var rawToolTip:String;
	
	public var position_original:flash.geom.Point;
	public var position_animate_to:flash.geom.Point;
	
	public function new ( index: Int, value:Properties ) {
		super();
		this.color = value.get('color');
		this.slice_angle = value.get('angle');
		this.border_width = 1;
		this.angle = value.get('start');
		this.animate = value.get('animate');
		this.nolabels = value.get('onclickabels');
		this.value = value.get('value');
		this.gradientFill = value.get('gradient-fill');
		
		this.index = index;
		this.rawToolTip = value.get('tip');
		
		this.label = this.replace_magic_values( value.get('label') );
		this.tooltip = this.replace_magic_values( value.get('tip') );
		
		// TODO: why is this commented out in the patch file?
		// this.attach_events();
		
		if ( value.has('onclick') )
			this.set_onclick( value.get('onclick') );
		
		this.finished_animating = false;
	}
	
	//
	// This is called by the tooltip when it is finished with us,
	// it is only used in modes the pie does not support
	//
	public override function set_tip( b:Bool ):Void {}
	
	//
	// for most objects this is handled in Element,
	// and this tip is displayed just above that object,
	// but for PieSlice we want the tooltip to follow
	// the mouse:
	//
	public override function get_tip_pos():{ x:Float, y:Float } {
		var p:flash.geom.Point = this.localToGlobal( new flash.geom.Point(this.mouseX, this.mouseY) );
		return {x:p.x,y:p.y};
	}

	function replace_magic_values( t:String ): String {
		
		t = StringTools.replace(t,'#label#', this.label );
		t = StringTools.replace(t,'#val#', NumberUtils.formatNumber( this.value ));
		t = StringTools.replace(t,'#radius#', NumberUtils.formatNumber( this.pieRadius ));
		return t;
	}
	
	public override function get_tooltip():String {
		this.tooltip = this.replace_magic_values( this.rawToolTip );
		return this.tooltip;
	}
	
	//
	// the axis makes no sense here, let's override with null and write our own.
	//
	public override function resize ( sc:ScreenCoordsBase ): Void { }
	public function pie_resize( sc:ScreenCoordsBase, radius: Float): Void {
		
		this.pieRadius = radius;
		this.x = sc.get_center_x();
		this.y = sc.get_center_y();
		
		var label_line_length: Float = 10;
		
		this.graphics.clear();
		
		//line from center to edge
		this.graphics.lineStyle( this.border_width, this.color, 1 );
		//this.graphics.lineStyle( 0, 0, 0 );

		//if the user selected the charts to be gradient filled do gradients
		if( this.gradientFill )
		{
			//set gradient fill
			var colors:Array<Float> = [this.color, this.color];// this.color];
			var alphas:Array<Float> = [1, 0.5];
			var ratios:Array<Int> = [100,255];
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(radius*2, radius*2, 0, -radius, -radius);
			
			//matrix.createGradientBox(this.stage.stageWidth, this.stage.stageHeight, (3 * Math.PI / 2), -150, 10);
			
			this.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix);
		}
		else
			this.graphics.beginFill(this.color, 1);
		
		this.graphics.moveTo(0, 0);
		this.graphics.lineTo(radius, 0);
		
		var angle: Float = 4;
		var a: Float = Math.tan((angle/2)*TO_RADIANS);
		
		var i: Float = 0;
		var endx: Float;
		var endy: Float;
		var ax: Float;
		var ay: Float;
			
		//draw curve segments spaced by angle
// 		for ( i = 0; i + angle < this.slice_angle; i += angle) {
// 			endx = radius*Math.cos((i+angle)*TO_RADIANS);
// 			endy = radius*Math.sin((i+angle)*TO_RADIANS);
// 			ax = endx+radius*a*Math.cos(((i+angle)-90)*TO_RADIANS);
// 			ay = endy+radius*a*Math.sin(((i+angle)-90)*TO_RADIANS);
// 			this.graphics.curveTo(ax, ay, endx, endy);
// 		}

		i = 0;
		// TODO - refactor that  i+angle shit away
		while (i + angle < this.slice_angle) {
			endx = radius*Math.cos((i+angle)*TO_RADIANS);
			endy = radius*Math.sin((i+angle)*TO_RADIANS);
			ax = endx+radius*a*Math.cos(((i+angle)-90)*TO_RADIANS);
			ay = endy+radius*a*Math.sin(((i+angle)-90)*TO_RADIANS);
			this.graphics.curveTo(ax, ay, endx, endy);
			i += angle;
		}
		

		//when aproaching end of slice, refine angle Interval
		angle = 0.08;
		a = Math.tan((angle/2)*TO_RADIANS);
		
// 		for ( ; i+angle < slice_angle; i+=angle) {
// 			endx = radius*Math.cos((i+angle)*TO_RADIANS);
// 			endy = radius*Math.sin((i+angle)*TO_RADIANS);
// 			ax = endx+radius*a*Math.cos(((i+angle)-90)*TO_RADIANS);
// 			ay = endy+radius*a*Math.sin(((i+angle)-90)*TO_RADIANS);
// 			this.graphics.curveTo(ax, ay, endx, endy);
// 		}

		while (i+angle < slice_angle) {
			endx = radius*Math.cos((i+angle)*TO_RADIANS);
			endy = radius*Math.sin((i+angle)*TO_RADIANS);
			ax = endx+radius*a*Math.cos(((i+angle)-90)*TO_RADIANS);
			ay = endy+radius*a*Math.sin(((i+angle)-90)*TO_RADIANS);
			this.graphics.curveTo(ax, ay, endx, endy);
			i+=angle;
		}


		//close slice
		this.graphics.endFill();
		this.graphics.lineTo(0, 0);
		
		if (!this.nolabels) this.draw_label_line( radius, label_line_length, this.slice_angle );
		// return;
		
		
		if( this.animate )
		{
			if ( !this.finished_animating ) {
				this.finished_animating = true;
				// have we already rotated this slice?
				Tweener.addTween(this, { rotation:this.angle, time:1.4, transition:Equations.easeOutCirc, onComplete:this.done_animating } );
			}
		}
		else
		{
			this.done_animating();
		}
	}
	
	function done_animating():Void {
		this.rotation = this.angle;
		this.finished_animating = true;
	}
	
	
	// draw the line from the pie slice to the label
		function draw_label_line( rad: Float, tick_size: Float, slice_angle: Float ):Void {
		//draw line
		
		// TODO: why is this commented out?
		//this.graphics.lineStyle( 1, this.color, 100 );
		//move to center of arc
		
		// TODO: need this?
		//this.graphics.moveTo(rad*Math.cos(slice_angle/2*TO_RADIANS), rad*Math.sin(slice_angle/2*TO_RADIANS));
	//
		//final line positions
		//var lineEnd_x: Float = (rad+tick_size)*Math.cos(slice_angle/2*TO_RADIANS);
		//var lineEnd_y: Float = (rad+tick_size)*Math.sin(slice_angle/2*TO_RADIANS);
		//this.graphics.lineTo(lineEnd_x, lineEnd_y);
	}
	
	
	public function toString ():String {
		return "PieSlice: "+ this.get_tooltip();
	}
	
	public function getTicAngle (): Float {
		return this.angle + (this.slice_angle / 2);
	}

	public function isRightSide ():Bool
	{
		return (this.getTicAngle() >= 270) || (this.getTicAngle() <= 90);
	}
	
	public function get_color(): Float {
		return this.color;
	}
}
